#include "hf_hal_gpio.h"


// 内部函数：获取 GPIO 端口的 RCC 时钟
static int8_t hf_gpio_get_rcc_periph(GPIO_TypeDef *port)
{
    if (port == GPIOA) return RCC_AHB1Periph_GPIOA;
    if (port == GPIOB) return RCC_AHB1Periph_GPIOB;
    if (port == GPIOC) return RCC_AHB1Periph_GPIOC;
    if (port == GPIOD) return RCC_AHB1Periph_GPIOD;
    if (port == GPIOE) return RCC_AHB1Periph_GPIOE;
    if (port == GPIOF) return RCC_AHB1Periph_GPIOF;
    if (port == GPIOG) return RCC_AHB1Periph_GPIOG;
    if (port == GPIOH) return RCC_AHB1Periph_GPIOH;
    if (port == GPIOI) return RCC_AHB1Periph_GPIOI;
    return 0; // 无效端口
}

// 内部函数：将引脚转换为 EXTI 引脚源
static int8_t hf_gpio_pin_to_source(uint16_t pin)
{
    for (uint8_t i = 0; i < 16; i++) {
        if (pin == (1U << i)) return i;
    }
    return -1; // 无效引脚
}

// 初始化 GPIO
int8_t hf_gpio_init(const hf_gpio_config_t *config)
{
    if (!config || !config->port || !config->pin) return GPIO_ERROR;

    // 使能 GPIO 时钟
    int8_t rcc_periph = hf_gpio_get_rcc_periph(config->port);
    if (!rcc_periph) return GPIO_ERROR;
    RCC_AHB1PeriphClockCmd(rcc_periph, ENABLE);

    // 配置 GPIO
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = config->pin;
    switch (config->mode) {
        case HF_GPIO_MODE_INPUT:
            GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
            break;
        case HF_GPIO_MODE_OUTPUT:
            GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
            GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
            break;
        case HF_GPIO_MODE_AF:
            GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
            GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
            break;
        case HF_GPIO_MODE_ANALOG:
            GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
            break;
        case HF_GPIO_MODE_OUTPUT_OD:
            GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
            GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
            break;
        default:
            return GPIO_ERROR;
    }

    switch (config->pupd) {
        case HF_GPIO_PUPD_NOPULL:
            GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
            break;
        case HF_GPIO_PUPD_UP:
            GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
            break;
        case HF_GPIO_PUPD_DOWN:
            GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
            break;
        default:
            return GPIO_ERROR;
    }

    switch (config->speed) {
        case HF_GPIO_SPEED_LOW:
            GPIO_InitStruct.GPIO_Speed = GPIO_Low_Speed;
            break;
        case HF_GPIO_SPEED_MEDIUM:
            GPIO_InitStruct.GPIO_Speed = GPIO_Medium_Speed;
            break;
        case HF_GPIO_SPEED_HIGH:
            GPIO_InitStruct.GPIO_Speed = GPIO_High_Speed;
            break;
        case HF_GPIO_SPEED_VERY_HIGH:
            GPIO_InitStruct.GPIO_Speed = GPIO_Very_High_Speed;
            break;
        default:
            return GPIO_ERROR;
    }

    GPIO_Init(config->port, &GPIO_InitStruct);

    // 如果是复用模式，配置 AF
    if (config->mode == HF_GPIO_MODE_AF) {
        GPIO_PinAFConfig(config->port, hf_gpio_pin_to_source(config->pin), config->af);
    }

    return GPIO_OK;
}

// 写 GPIO 引脚电平
int8_t hf_gpio_write(GPIO_TypeDef *port, uint16_t pin, uint8_t state)
{
    if (!port || !pin) return GPIO_ERROR;

    GPIO_WriteBit(port, pin, state ? Bit_SET : Bit_RESET);
    return GPIO_OK;
}

int8_t hf_gpio_read(GPIO_TypeDef *port, uint16_t pin)
{
    if (!port || !pin) return GPIO_ERROR;

    return GPIO_ReadInputDataBit(port, pin) ? 1 : 0;
}

// 翻转 GPIO 引脚电平
int8_t hf_gpio_toggle(GPIO_TypeDef *port, uint16_t pin)
{
    if (!port || !pin) return GPIO_ERROR;

    GPIO_ToggleBits(port, pin);
    return GPIO_OK;
}

// 配置 GPIO 中断
int8_t hf_gpio_init_irq(const hf_gpio_irq_config_t *config)
{
    if (!config || !config->port || !config->pin || !config->handler || config->exti_line > 15) return GPIO_ERROR;

    // 使能 GPIO 时钟
    uint32_t rcc_periph = hf_gpio_get_rcc_periph(config->port);
    if (!rcc_periph) return GPIO_ERROR;
    RCC_AHB1PeriphClockCmd(rcc_periph, ENABLE);

    // 配置 GPIO 为输入模式
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = config->pin;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
    switch (config->pupd) {
        case HF_GPIO_PUPD_NOPULL:
            GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
            break;
        case HF_GPIO_PUPD_UP:
            GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
            break;
        case HF_GPIO_PUPD_DOWN:
            GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
            break;
        default:
            return GPIO_ERROR;
    }
    GPIO_Init(config->port, &GPIO_InitStruct);

    // 使能 SYSCFG 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

    // 配置 EXTI 线
    SYSCFG_EXTILineConfig(
        (config->port == GPIOA) ? EXTI_PortSourceGPIOA :
        (config->port == GPIOB) ? EXTI_PortSourceGPIOB :
        (config->port == GPIOC) ? EXTI_PortSourceGPIOC :
        (config->port == GPIOD) ? EXTI_PortSourceGPIOD :
        EXTI_PortSourceGPIOE, // 根据实际硬件调整
        hf_gpio_pin_to_source(config->pin)
    );

    EXTI_InitTypeDef EXTI_InitStruct;
    EXTI_InitStruct.EXTI_Line = config->exti_line;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    switch (config->trigger) {
        case HF_GPIO_IRQ_TRIGGER_RISING:
            EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
            break;
        case HF_GPIO_IRQ_TRIGGER_FALLING:
            EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
            break;
        case HF_GPIO_IRQ_TRIGGER_BOTH:
            EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
            break;
        default:
            return GPIO_ERROR;
    }
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStruct);

    // 配置 NVIC
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = (config->exti_line == EXTI_Line0) ? EXTI0_IRQn :
                                     (config->exti_line == EXTI_Line1) ? EXTI1_IRQn :
                                     (config->exti_line == EXTI_Line2) ? EXTI2_IRQn :
                                     (config->exti_line == EXTI_Line3) ? EXTI3_IRQn :
                                     (config->exti_line == EXTI_Line4) ? EXTI4_IRQn :
                                     (config->exti_line <= EXTI_Line9) ? EXTI9_5_IRQn :
                                     EXTI15_10_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = config->priority;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);

    return GPIO_OK;
}

// 中断服务处理
void hf_gpio_handle_irq(uint32_t exti_line)
{

    // 检查中断状态
    if (EXTI_GetITStatus(exti_line) != RESET) {
        //业务逻辑
        
        // 清除中断标志
        EXTI_ClearITPendingBit(exti_line);
    }
}

// STM32 EXTI 中断服务例程
void EXTI0_IRQHandler(void) 
{ 
    hf_gpio_handle_irq(EXTI_Line0); 
}

void EXTI1_IRQHandler(void) 
{ 
    hf_gpio_handle_irq(EXTI_Line1); 
}

void EXTI2_IRQHandler(void) 
{ 
    hf_gpio_handle_irq(EXTI_Line2); 
}

void EXTI3_IRQHandler(void) 
{ 
    hf_gpio_handle_irq(EXTI_Line3); 
}

void EXTI4_IRQHandler(void) 
{ 
    hf_gpio_handle_irq(EXTI_Line4); 
}

void EXTI9_5_IRQHandler(void) 
{
    if (EXTI_GetITStatus(EXTI_Line5) != RESET) hf_gpio_handle_irq(EXTI_Line5);
    if (EXTI_GetITStatus(EXTI_Line6) != RESET) hf_gpio_handle_irq(EXTI_Line6);
    if (EXTI_GetITStatus(EXTI_Line7) != RESET) hf_gpio_handle_irq(EXTI_Line7);
    if (EXTI_GetITStatus(EXTI_Line8) != RESET) hf_gpio_handle_irq(EXTI_Line8);
    if (EXTI_GetITStatus(EXTI_Line9) != RESET) hf_gpio_handle_irq(EXTI_Line9);
}
void EXTI15_10_IRQHandler(void)
 {
    if (EXTI_GetITStatus(EXTI_Line10) != RESET) hf_gpio_handle_irq(EXTI_Line10);
    if (EXTI_GetITStatus(EXTI_Line11) != RESET) hf_gpio_handle_irq(EXTI_Line11);
    if (EXTI_GetITStatus(EXTI_Line12) != RESET) hf_gpio_handle_irq(EXTI_Line12);
    if (EXTI_GetITStatus(EXTI_Line13) != RESET) hf_gpio_handle_irq(EXTI_Line13);
    if (EXTI_GetITStatus(EXTI_Line14) != RESET) hf_gpio_handle_irq(EXTI_Line14);
    if (EXTI_GetITStatus(EXTI_Line15) != RESET) hf_gpio_handle_irq(EXTI_Line15);
}
